package piwan.gui;

import java.io.File;

import javax.media.opengl.GL;

import org.fenggui.Display;
import org.fenggui.FengGUI;
import org.fenggui.Label;
import org.fenggui.appearance.LabelAppearance;
import org.fenggui.binding.render.text.ITextRenderer;
import org.fenggui.util.Alignment;
import org.fenggui.util.Point;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;

import piwan.*;

public class CombatWindow {
	private static final String combatWindowTexFile = "gfx/combatwin.png"; 
	private static final String hiddenTexFile = "gfx/cw_numleft.png";
	private static final String guessedTexFile = "gfx/cw_numright.png";
	private Vector2 vall1,vall2,vhid1,vhid2,vgss1,vgss2;
	private GameState gstate;
	private Label hiddenlbl, guessedlbl, titlelbl, attlbl, deflbl, roundlbl, regslbl,hidcaplbl,gsscaplbl;
	private Display disp;
	private LabelTable table;
	private int roundno=1;
	private GL gl;
	private Player att, def;
	private Region rto,rfrom;
	private boolean hasExtraDef = false;
	private Colour backgroundTint = noTint;
	static private Texture winTex=null,hidTex=null,gssTex=null;
	static private final Colour noTint = new Colour(1.0,1.0,1.0,1.0);
	private static int relsz(int size, double ratio) { return (int)Math.round(size*ratio); }
	
	
	public CombatWindow(MainWindow win, GameState gstate) {
		this.gstate = gstate;
		gl = win.getGL();
		disp = win.getDisplay();
		
		
		att = gstate.getAttacking();
		def = gstate.getDefending();
		rto = gstate.getCombatTo();
		rfrom = gstate.getCombatFrom();
		hasExtraDef = rto.getType().getDefenseBonus()>0;
		
		createWidgets();
		resetNumbers();
		setCombatInfo();
		newRound();
		//setPositions(relsz(disp.getWidth(),.378*1.5/),relsz(disp.getHeight(),.391*1.5));
		setPositions(1088,704);
		
		if(winTex == null) {
			try {
				
				winTex = TextureIO.newTexture(new File(combatWindowTexFile), false);
				hidTex = TextureIO.newTexture(new File(hiddenTexFile), false);
				gssTex = TextureIO.newTexture(new File(guessedTexFile), false);
				
			} catch(Exception e) {
				MainWindow.die(e);
			
			}
		}
		
	}
	
	public void cancelled() {
		roundlbl.setText("Cancelled");
		titlelbl.setText("Combat Ended - " + att.getName() + " retreated!");
	}
	
	private void doColour(Colour c) {
		gl.glColor4d(c.r,c.g,c.b,c.a);
	}
	
	private void doColour(Colour c,double a) {
		gl.glColor4d(c.r,c.g,c.b,a);
	}
	
	public void render() {
		gl.glDisable(GL.GL_DEPTH_TEST);
		gl.glEnable(GL.GL_TEXTURE_2D);
		gl.glEnable(GL.GL_BLEND);
		gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
		doColour(backgroundTint,0.9);
		winTex.bind();
		GameGui.renderRect(gl,vall1,vall2);
		doColour(att.getColour());
		hidTex.bind();
		GameGui.renderRect(gl,vhid1,vhid2);
		doColour(def.getColour());
		gssTex.bind();
		GameGui.renderRect(gl,vgss1,vgss2);
		
	}
	
	public void remove() {
		table.removeWidgets();
		disp.removeWidget(roundlbl,hiddenlbl,guessedlbl,titlelbl,attlbl,deflbl,regslbl,hidcaplbl,gsscaplbl);
	}
	
	public void endRound(int h, int g, boolean newRound) {
		hiddenlbl.setText(Integer.toString(h));
		guessedlbl.setText(Integer.toString(g));
		++roundno;
		
		
		if(newRound) {
			if(h==g) {
				//roundlbl.setText(def.getName() + " won!");
				backgroundTint = def.getColour();
				roundlbl.setText(att.getName() + " lost " + GameGui.ntroop(h) + ".");	
			} else {
				//roundlbl.setText(att.getName() + " won!");
				backgroundTint = att.getColour();
				
				if(hasExtraDef) {
					roundlbl.setText(def.getName() + " lost 1 defense.");
					hasExtraDef = false;
				} else
					roundlbl.setText(def.getName() + " lost 1 troop.");
			}
			setSoldiers(false);
		} else if(!newRound) {
			setSoldiers(true);
			if(h==g) {
				backgroundTint = def.getColour();
				roundlbl.setText(def.getName() + " won!");
				titlelbl.setText("Combat Ended - " + def.getName() + " defended successfully!");
			} else {
				backgroundTint = att.getColour();
				roundlbl.setText(att.getName() + " won!");
				titlelbl.setText("Combat Ended - " + att.getName() + " conquered " + rto.getName() + "!");
			}
		}
	}
	
	public void newRound() {
		backgroundTint = noTint;
		setRound(roundno);
		setSoldiers(false);
		resetNumbers();
	}
	
	private void createWidgets() {
		hiddenlbl = FengGUI.createWidget(Label.class);
		guessedlbl = FengGUI.createWidget(Label.class);
		roundlbl = FengGUI.createWidget(Label.class);
		titlelbl = FengGUI.createWidget(Label.class);
		attlbl = FengGUI.createWidget(Label.class);
		deflbl = FengGUI.createWidget(Label.class);
		regslbl = FengGUI.createWidget(Label.class);
		hidcaplbl = FengGUI.createWidget(Label.class);
		gsscaplbl = FengGUI.createWidget(Label.class);
		
		LabelAppearance app = hiddenlbl.getAppearance();
		ITextRenderer trTitle = app.getRenderer("combatTitle");
		ITextRenderer trRound = app.getRenderer("combatTitle");
		ITextRenderer trNumber = app.getRenderer("combatNumber");
		ITextRenderer trNormal = app.getRenderer("combatText");
		
		hiddenlbl.getAppearance().addRenderer("default", trNumber);
		guessedlbl.getAppearance().addRenderer("default", trNumber);
		titlelbl.getAppearance().addRenderer("default", trTitle);
		roundlbl.getAppearance().addRenderer("default", trRound);
		regslbl.getAppearance().addRenderer("default", trRound);
		attlbl.getAppearance().addRenderer("default", trNormal);
		deflbl.getAppearance().addRenderer("default", trNormal);
		hidcaplbl.getAppearance().addRenderer("default", trNormal);
		gsscaplbl.getAppearance().addRenderer("default", trNormal);
		hiddenlbl.getAppearance().setAlignment(Alignment.MIDDLE);
		guessedlbl.getAppearance().setAlignment(Alignment.MIDDLE);
		titlelbl.getAppearance().setAlignment(Alignment.MIDDLE);
		roundlbl.getAppearance().setAlignment(Alignment.MIDDLE);
		regslbl.getAppearance().setAlignment(Alignment.MIDDLE);
		attlbl.getAppearance().setAlignment(Alignment.MIDDLE);
		deflbl.getAppearance().setAlignment(Alignment.MIDDLE);
		
		table = new LabelTable(disp,3, trNormal,trNormal);
		hidcaplbl.setText(att.getName() + "'s hidden number:");
		gsscaplbl.setText(def.getName() + "'s guess:");
		disp.addWidget(hiddenlbl,guessedlbl,titlelbl,roundlbl,regslbl,attlbl,deflbl,hidcaplbl,gsscaplbl);
	}
	
	private void resetNumbers() {
		hiddenlbl.setText("?");
		guessedlbl.setText("?");
	}
	
	private void setCombatInfo() {
		titlelbl.setText(def.getName() + " is under attack by " + att.getName()  );
		regslbl.setText("");
		table.setName(0, "Region Type:");
		table.setName(1, "Max. Attack:");
		table.setName(2, "Defense Bonus:");
		table.setValue(0, gstate.getCombatTo().getType().getName());
		table.setValue(1, Integer.toString(gstate.getCombatTo().getType().getMaxAttack()));
		if( !hasExtraDef )
			table.setValue(2, "-");
		else
			table.setValue(2, "+" + rto.getType().getDefenseBonus());
	}
	
	private void setSoldiers( boolean reversed ) {
		if(reversed) {
			attlbl.setText(att.getName() + " (" + rto.getName() + ") - " +GameGui.ntroop(rto.getSoldiers()) + ". ");
			deflbl.setText(def.getName() + " lost " + rto.getName() + ".");
		} else {
			attlbl.setText(att.getName() + " (" + rfrom.getName() + ") - " + GameGui.ntroop(rfrom.getSoldiers()) + ".");
			String defstr = def.getName() + " (" + rto.getName() + ") - " +  GameGui.ntroop(rto.getSoldiers());
			int extradef = rto.getExtraDefense();
			if( extradef>0 )
				defstr += " + " + extradef + " bonus";
			
			deflbl.setText(defstr + ".");
		}
		
	}
	
	private void setRound(int n) {
		if( n!=0 )
			roundlbl.setText("Round " + n);
		else
			roundlbl.setText("Combat Ended");
	}
	
	
	static private final double titleHeight = 0.121276;
	static private final double titleNumberSpacing = 8.44680e-2;
	static private final double bottomSpacing = 0.1;
	static private final double soldsHeight = 0.04;
	static private final double roundHeight = 0.182978;
	static private final double winnerRoundOverlap = 0.08;
	static private final double winnerHeight = 0.1063829;
	//static private final double winnerTableSpacing = 0.17021276;
	static private final double horizSpacing = 8.37912e-2;
	static private final double numberWidth = 0.2513736;
	static private final double numberHeight = 1.0 - titleHeight - titleNumberSpacing - soldsHeight - bottomSpacing;
	static private final double roundWidth = 1.0 - 2.0*numberWidth - 2.0*horizSpacing;
	
	
	private void setPositions(int width, int height) {
		int cx = disp.getWidth()/2;
		int sx = cx - width / 2;
		int sy = disp.getHeight()/2 + height/2;
		
		int hidx = sx + relsz(width,horizSpacing);
		int hidy = sy - relsz(height,titleHeight) - relsz(height, titleNumberSpacing) - relsz(height,numberHeight);
		
		titlelbl.setSize(width, relsz(height,titleHeight));
		titlelbl.setPosition( new Point(sx,sy-titlelbl.getHeight()) );
		
		/*
		hiddenlbl.setSize(					relsz(width,numberWidth), 				relsz(height,numberHeight));
		hiddenlbl.setPosition(new Point(	hidx,									hidy));
		
		guessedlbl.setSize(hiddenlbl.getSize());
		guessedlbl.setPosition(new Point(hidx+hiddenlbl.getWidth() + relsz(width,roundWidth), hidy) );
		
		attlbl.setSize(						relsz(width,1.0/2.0),					relsz(height,soldsHeight));
		attlbl.setPosition(new Point(		hidx+hiddenlbl.getWidth()/2-attlbl.getWidth()/2, hidy-attlbl.getHeight()));
		
		deflbl.setSize(attlbl.getSize());
		deflbl.setPosition(new Point(		guessedlbl.getX()+guessedlbl.getWidth()/2-attlbl.getWidth()/2, attlbl.getY()));
		
		//hidcaplbl.setSize(						hiddenlbl.getWidth(),					relsz(height,soldsHeight/1.5));
		hidcaplbl.setPosition(new Point(		hidx, hidy+hiddenlbl.getHeight()));
		
		//gsscaplbl.setSize(						guessedlbl.getWidth(),					relsz(height,soldsHeight/1.5));
		gsscaplbl.setPosition(new Point(		guessedlbl.getX(),						hidcaplbl.getY()));
		*/
		
		
		
		guessedlbl.setSize(					relsz(width,numberWidth), 				relsz(height,numberHeight));
		guessedlbl.setPosition(new Point(	hidx,									hidy));
		
		hiddenlbl.setSize(guessedlbl.getSize());
		hiddenlbl.setPosition(new Point(hidx+guessedlbl.getWidth() + relsz(width,roundWidth), hidy) );
		
		deflbl.setSize(						relsz(width,1.0/2.0),					relsz(height,soldsHeight));
		deflbl.setPosition(new Point(		hidx+guessedlbl.getWidth()/2-deflbl.getWidth()/2, hidy-deflbl.getHeight()));
		
		attlbl.setSize(deflbl.getSize());
		attlbl.setPosition(new Point(		hiddenlbl.getX()+hiddenlbl.getWidth()/2-attlbl.getWidth()/2, deflbl.getY()));
		
		//hidcaplbl.setSize(						hiddenlbl.getWidth(),					relsz(height,soldsHeight/1.5));
		gsscaplbl.setPosition(new Point(		hidx, hidy+guessedlbl.getHeight()));
		
		//gsscaplbl.setSize(						guessedlbl.getWidth(),					relsz(height,soldsHeight/1.5));
		hidcaplbl.setPosition(new Point(		hiddenlbl.getX(),						gsscaplbl.getY()));
		
		/*
		regslbl.setSize(						relsz(width,roundWidth),				relsz(height,roundHeight));
		regslbl.setPosition(new Point(		guessedlbl.getX()+guessedlbl.getWidth(),	hidy+guessedlbl.getHeight()-regslbl.getHeight()));
		roundlbl.setSize(					relsz(width,roundWidth),				relsz(height,winnerHeight));
		roundlbl.setPosition(new Point(	regslbl.getX(),						regslbl.getY()-roundlbl.getHeight()+relsz(height,winnerRoundOverlap)));
		*/
		
		roundlbl.setSize(					relsz(width,roundWidth),				relsz(height,roundHeight));
		roundlbl.setPosition(new Point(		guessedlbl.getX()+hiddenlbl.getWidth(),	hidy+guessedlbl.getHeight()-roundlbl.getHeight()));
		regslbl.setSize(					relsz(width,roundWidth),				relsz(height,winnerHeight));
		regslbl.setPosition(new Point(	roundlbl.getX(),						roundlbl.getY()-regslbl.getHeight()+relsz(height,winnerRoundOverlap)));
		
		
		table.position(cx, hidy-100);
		
		vall1 = new Vector2();
		vall2 = new Vector2();
		vhid1 = new Vector2();
		vhid2 = new Vector2();
		vgss1 = new Vector2();
		vgss2 = new Vector2();
		
		vall1.x = (double)sx/disp.getWidth();
		vall2.x = vall1.x + (double)width/disp.getWidth();
		vall1.y = (double)sy/disp.getHeight();
		vall2.y = vall1.y - (double)height/disp.getHeight();
		vall1.x = vall1.x*2.0-1.0;
		vall2.x = vall2.x*2.0-1.0;
		vall1.y = vall1.y*2.0-1.0;
		vall2.y = vall2.y*2.0-1.0;
		
		widgetToWorld(vhid1,vhid2,hiddenlbl);
		widgetToWorld(vgss1,vgss2,guessedlbl);
		
	}
	
	private void widgetToWorld(Vector2 v1, Vector2 v2, Label w) {
		v1.x = ((double)w.getX()/disp.getWidth())*2.0 - 1.0;
		v2.x = ((double)(w.getX()+w.getWidth())/disp.getWidth())*2.0 - 1.0;
		v1.y = ((double)w.getY()/disp.getHeight())*2.0 - 1.0;
		v2.y = ((double)(w.getY()+w.getHeight())/disp.getHeight())*2.0 - 1.0;
	}
}
